package cn.edu.jssvc.litai.bluetoothtest238;

import android.Manifest;
import android.app.Activity;
import android.bluetooth.BluetoothA2dp;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private static final int SCANNED_DEVICE = 1;
    private static final int BONDED_DEVICE = 2;
    private static final int BOND_NONE_DEVICE = 3;
    private Button onOffBtn;
    private Button scanDevicesBtn;
    private ListView showDevicesListview;

    final String A2DP_ADDRESS="2C:C5:46:61:12:AC";
   // 74:A3:4A:BD:C1:CF
    BluetoothDevice a2dpDevice;

    BluetoothDevice bluetoothDevice;
    Message message;

    BluetoothAdapter bluetoothAdapter;
    boolean isSupport;

    BluetoothReceiver bluetoothReceiver;
    IntentFilter intentFilter;

    List<BluetoothDevice> scannedDeviceList = new ArrayList<>();
    List<String> scannedDeviceInfoList = new ArrayList<>();//List:有序，可以重复
    Set<String> scannedDeviceSet = new HashSet<>();//Set:无序，不可以重复
    ArrayAdapter<String> arrayAdapter;

    List<BluetoothDevice> bondDeviceList = new ArrayList<>();
    List<String> bondDeviceInfoList = new ArrayList<>();//List:有序，可以重复
    Set<String> bondDeviceSet = new HashSet<>();//Set:无序，不可以重复
    ArrayAdapter<String> arrayAdapterBond;

    BluetoothDevice bondDevice;

    BluetoothA2dp bluetoothA2dp;

    void getBluetoothA2dp(){
        if(bluetoothAdapter==null){
            return;
        }
        if(bluetoothA2dp!=null){
            return;
        }

        bluetoothAdapter.getProfileProxy(this, new BluetoothProfile.ServiceListener() {
            @Override
            public void onServiceConnected(int profile, BluetoothProfile proxy) {
                if(profile==BluetoothA2dp.A2DP){//获取BluetoothA2dp对象
                    bluetoothA2dp=(BluetoothA2dp) proxy;
                }
            }

            @Override
            public void onServiceDisconnected(int profile) {

            }
        }, BluetoothA2dp.A2DP);
    }

    void connectA2dpDevice(BluetoothDevice device,String connectInfo){
        try {
            Method method=BluetoothA2dp.class.getMethod(connectInfo,BluetoothDevice.class);
            method.setAccessible(true);
            method.invoke(bluetoothA2dp,device);
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    Handler myHandler = new Handler() {
        @Override
        public void handleMessage(@NonNull Message msg) {
            switch (msg.what) {
                case BONDED_DEVICE:
                    String bondDeviceInfo = bondDevice.getName() + ";" + bondDevice.getAddress();
                    if (bondDeviceSet.add(bondDeviceInfo)) {
                        bondDeviceInfoList.add(bondDeviceInfo);
                        bondDeviceList.add(bondDevice);
                        scannedDeviceInfoList.remove(bondDeviceInfo);
                        scannedDeviceList.remove(bondDevice);
                        scannedDeviceSet.remove(bondDeviceInfo);
//                        showDevices();
                        arrayAdapter.notifyDataSetChanged();
                        arrayAdapterBond.notifyDataSetChanged();
                    }
                    break;
                case BOND_NONE_DEVICE:
                    String bondNoneDeviceInfo = bondDevice.getName() + ";" + bondDevice.getAddress();
                    if (scannedDeviceSet.add(bondNoneDeviceInfo)) {
                        bondDeviceInfoList.remove(bondNoneDeviceInfo);
                        bondDeviceList.remove(bondDevice);
                        bondDeviceSet.remove(bondNoneDeviceInfo);
                        scannedDeviceInfoList.add(bondNoneDeviceInfo);
                        scannedDeviceList.add(bondDevice);
//                        showDevices();
                        arrayAdapter.notifyDataSetChanged();
                        arrayAdapterBond.notifyDataSetChanged();
                    }
                    break;
                case SCANNED_DEVICE://SCANNED_DEVICE=1
                    if (bluetoothDevice.getBondState() == BluetoothDevice.BOND_NONE) {
                        String deviceInfo = bluetoothDevice.getName() + ";" + bluetoothDevice.getAddress();
                        if (scannedDeviceSet.add(deviceInfo)) {//如果存入Set，则返回true，如果内容重复不会存入Set，则返回false
                            scannedDeviceList.add(bluetoothDevice);
                            scannedDeviceInfoList.add(deviceInfo);
                            showDevices();//发现一个设备就刷新一下界面显示
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    };

    private ListView showBondDevicesListview;
    private Button connectBtn;
    private Button disconnectBtn;

    void showDevices() {
        arrayAdapter = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, scannedDeviceInfoList);
        showDevicesListview.setAdapter(arrayAdapter);

        showDevicesListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {//列表项的单击事件
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                bondDevice = scannedDeviceList.get(position);
                bondUtil(bondDevice, "createBond");//"createBond"：请求配对蓝牙设备
            }
        });

        showBondDevicesListview.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                bondDevice = bondDeviceList.get(position);
                bondUtil(bondDevice, "removeBond");//"removeBond"：请求取消配对蓝牙设备
            }
        });
    }

    void bondUtil(BluetoothDevice device, String bondInfo) {
        try {
            Method method = BluetoothDevice.class.getMethod(bondInfo);
            method.invoke(device);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initView();

        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (bluetoothAdapter != null) {
            isSupport = true;
            isGrantedPermission(this);
            a2dpDevice=bluetoothAdapter.getRemoteDevice(A2DP_ADDRESS);
            if (bluetoothAdapter.isEnabled() == true) {//蓝牙功能已开启
                onOffBtn.setText("OFF");
                getBluetoothA2dp();//设备蓝牙，蓝牙已开
            } else {//蓝牙功能已关闭
                onOffBtn.setText("ON");
            }
            bondDeviceList = new ArrayList<>(bluetoothAdapter.getBondedDevices());//Set直接转换成List
            if (bondDeviceList.size() > 0) {
                for (BluetoothDevice element : bondDeviceList) {
                    String info = element.getName() + ";" + element.getAddress();
                    bondDeviceInfoList.add(info);
                    bondDeviceSet.add(info);
                }

                arrayAdapterBond = new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, bondDeviceInfoList);
                showBondDevicesListview.setAdapter(arrayAdapterBond);
            }
            Toast.makeText(this, "该设备支持蓝牙", Toast.LENGTH_SHORT).show();
            Log.d("tag-create", "onCreate: 该设备支持蓝牙");
        } else {
            isSupport = false;
            Toast.makeText(this, "该设备不支持蓝牙", Toast.LENGTH_SHORT).show();
            Log.d("tag-create", "onCreate: 该设备不支持蓝牙");
        }
        bluetoothReceiver = new BluetoothReceiver();
        intentFilter = new IntentFilter();
        intentFilter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_STARTED);
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
        intentFilter.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
        intentFilter.addAction(BluetoothDevice.ACTION_PAIRING_REQUEST);
        intentFilter.addAction(BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED);
        intentFilter.addAction(BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED);
        registerReceiver(bluetoothReceiver, intentFilter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (bluetoothReceiver != null) {
            unregisterReceiver(bluetoothReceiver);
        }
        if(bluetoothAdapter!=null){
            if(bluetoothAdapter.isDiscovering()){
                bluetoothAdapter.cancelDiscovery();
            }
            bluetoothAdapter.closeProfileProxy(BluetoothProfile.A2DP,bluetoothA2dp);
        }
    }

    private void initView() {
        onOffBtn = (Button) findViewById(R.id.on_off_btn);
        scanDevicesBtn = (Button) findViewById(R.id.scan_devices_btn);
        showDevicesListview = (ListView) findViewById(R.id.show_devices_listview);

        onOffBtn.setOnClickListener(this);
        scanDevicesBtn.setOnClickListener(this);
        showBondDevicesListview = (ListView) findViewById(R.id.show_bond_devices_listview);

        connectBtn = (Button) findViewById(R.id.connect_btn);
        connectBtn.setOnClickListener(this);
        disconnectBtn = (Button) findViewById(R.id.disconnect_btn);
        disconnectBtn.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.on_off_btn:
                if (isSupport) {
                    if (bluetoothAdapter.isEnabled() == true) {//蓝牙功能已开启
//                        onOffBtn.setText("ON");
                        bluetoothAdapter.disable();//异步方法
                    } else {//蓝牙功能已关闭
//                        onOffBtn.setText("ON");
                        bluetoothAdapter.enable();//异步方法

                    }
                }

                break;
            case R.id.scan_devices_btn:
                if (isSupport) {
                    if (bluetoothAdapter.isEnabled()) {//蓝牙已开，开始扫描
                        bluetoothAdapter.startDiscovery();
                    } else {//蓝牙关闭，先开启蓝牙
                        bluetoothAdapter.enable();//异步方法
//                        bluetoothAdapter.startDiscovery();//不能在这里开始扫描
                    }
                }

                break;
            case R.id.connect_btn:
                if(bluetoothAdapter.isEnabled()==false){
                    bluetoothAdapter.enable();//异步方法
//                    getBluetoothA2dp();//不能在这里调用
                }else {
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            connectA2dpDevice(a2dpDevice,"connect");
                        }
                    }).start();
                }

                break;
            case R.id.disconnect_btn:
                if(a2dpDevice!=null){
                    connectA2dpDevice(a2dpDevice,"disconnect");
                }else {

                }
                break;
        }
    }


    class BluetoothReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            int a2dpState=intent.getIntExtra(BluetoothA2dp.EXTRA_STATE,BluetoothA2dp.STATE_DISCONNECTED);
            switch (intent.getAction()) {
                case BluetoothDevice.ACTION_ACL_CONNECTED:
                    Toast.makeText(MainActivity.this, "连接成功", Toast.LENGTH_SHORT).show();
                    Log.d("tag-create", "连接成功");
                    break;
                case BluetoothDevice.ACTION_ACL_DISCONNECTED:
                    Toast.makeText(MainActivity.this, "连接断开", Toast.LENGTH_SHORT).show();
                    Log.d("tag-create", "连接断开");
                    break;
                case BluetoothA2dp.ACTION_CONNECTION_STATE_CHANGED:
                    if(a2dpState==BluetoothA2dp.STATE_CONNECTED){
                        Toast.makeText(MainActivity.this, "多媒体设备连接成功", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "多媒体设备连接成功");
                    }else if(a2dpState==BluetoothA2dp.STATE_CONNECTING){
                        Toast.makeText(MainActivity.this, "多媒体设备连接中......", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "多媒体设备连接连接中......");
                    }else if(a2dpState==BluetoothA2dp.STATE_DISCONNECTED){
                        Toast.makeText(MainActivity.this, "多媒体设备连接断开", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "多媒体设备连接断开");
                    }
                    break;
                case BluetoothA2dp.ACTION_PLAYING_STATE_CHANGED:
                    if(a2dpState==BluetoothA2dp.STATE_NOT_PLAYING){
                        Toast.makeText(MainActivity.this, "多媒体设备不在播放", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "多媒体设备不在播放");
                    }else if(a2dpState==BluetoothA2dp.STATE_PLAYING){
                        Toast.makeText(MainActivity.this, "多媒体设备正在播放", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "多媒体设备正在播放");
                    }
                    break;
                case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
                    int bondState = bondDevice.getBondState();
                    if (bondState == BluetoothDevice.BOND_BONDED) {
                        Toast.makeText(MainActivity.this, "配对成功", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "配对成功");
                        message = new Message();
                        message.what = BONDED_DEVICE;
                        myHandler.sendMessage(message);
                    } else if (bondState == BluetoothDevice.BOND_BONDING) {
                        Toast.makeText(MainActivity.this, "配对中......", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "配对中......");
                    } else if (bondState == BluetoothDevice.BOND_NONE) {
                        Toast.makeText(MainActivity.this, "取消配对", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "取消配对");
                        message = new Message();
                        message.what = BOND_NONE_DEVICE;
                        myHandler.sendMessage(message);
                    }
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_STARTED:
                    Toast.makeText(MainActivity.this, "开始扫描", Toast.LENGTH_SHORT).show();
                    Log.d("tag-create", "onCreate: 开始扫描");
                    break;
                case BluetoothAdapter.ACTION_DISCOVERY_FINISHED:
                    Toast.makeText(MainActivity.this, "结束扫描", Toast.LENGTH_SHORT).show();
                    Log.d("tag-create", "onCreate: 结束扫描");
//                   bluetoothAdapter.cancelDiscovery();
                    break;
                case BluetoothDevice.ACTION_FOUND:
                    Toast.makeText(MainActivity.this, "发现蓝牙设备", Toast.LENGTH_SHORT).show();
                    Log.d("tag-create", "onCreate: 发现蓝牙设备");
                    //获取扫描到的蓝牙设备对象
                    bluetoothDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                    message = new Message();
                    message.what = SCANNED_DEVICE;
                    myHandler.sendMessage(message);
                    Log.d("tag-found", bluetoothDevice.getName() + ";" + bluetoothDevice.getAddress());
                    break;
                case BluetoothAdapter.ACTION_STATE_CHANGED:
                    if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
                        onOffBtn.setText("ON");
                        Toast.makeText(MainActivity.this, "蓝牙已关", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "onCreate: 蓝牙已关");
                    } else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_ON) {
                        onOffBtn.setText("OFF");
                        Toast.makeText(MainActivity.this, "蓝牙已开", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "onCreate: 蓝牙已开");
                        getBluetoothA2dp();
                        bluetoothAdapter.startDiscovery();
                    } else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_TURNING_OFF) {
                        Toast.makeText(MainActivity.this, "蓝牙正在关...", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "onCreate: 蓝牙正在关...");
                    } else if (bluetoothAdapter.getState() == BluetoothAdapter.STATE_TURNING_ON) {
                        Toast.makeText(MainActivity.this, "蓝牙正在开...", Toast.LENGTH_SHORT).show();
                        Log.d("tag-create", "onCreate: 蓝牙正在开...");
                    }
                    break;
                default:
                    break;
            }
        }
    }


    boolean isGrantedPermission(Activity activity) {
        if (Build.VERSION.SDK_INT >= 23 &&//判断系统版本及权限是否已经授权
                activity.checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            activity.requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                    Manifest.permission.ACCESS_FINE_LOCATION}, 1);
            return false;
        }
        return true;
    }
}